package comm

import (
	"bytes"
	"gitee.com/gcom/gbox/errors"
	"github.com/PuerkitoBio/goquery"
	"golang.org/x/net/html"
	"golang.org/x/text/encoding/simplifiedchinese"
)

type Charset string

const (
	UTF8    = Charset("UTF-8")
	GB18030 = Charset("GB18030")
)

// HTMLText 获取html节点下的文本，包括子节点
func HTMLText(node *html.Node) string {
	var buf bytes.Buffer

	var f func(*html.Node)
	f = func(n *html.Node) {
		if n.Type == html.TextNode {
			// Keep newlines and spaces, like jQuery
			buf.WriteString(n.Data)
		}
		if n.FirstChild != nil {
			for c := n.FirstChild; c != nil; c = c.NextSibling {
				f(c)
			}
		}
	}
	f(node)

	return buf.String()
}

// HTMLNodeText 获取节点下的直接文本，不包括子节点
func HTMLNodeText(s *goquery.Selection) string {
	var text string
	s.Contents().Each(func(i int, s *goquery.Selection) {
		if goquery.NodeName(s) == "#text" {
			text += s.Text()
		}
	})
	return text
}

// HTMLAttr 获取html节点的属性
func HTMLAttr(node *html.Node, attrName string) (string, bool) {
	if node == nil {
		return "", false
	}

	var attr *html.Attribute
	for i, a := range node.Attr {
		if a.Key == attrName {
			attr = &node.Attr[i]
			return attr.Val, true
		}
	}
	return "", false
}

// HTMLAttrOr works like Attr but returns default value if attribute is not present.
func HTMLAttrOr(node *html.Node, attrName, defaultValue string) string {
	val, exists := HTMLAttr(node, attrName)
	if !exists {
		return defaultValue
	}
	return val
}

// GetHTMLDoc 获取并解析网页
func GetHTMLDoc(bs []byte, charset Charset) (*goquery.Document, error) {
	utf8, err := Convert2Utf8(bs, charset)
	if err != nil {
		return nil, errors.Wrap(err, "响应数据编码转换失败")
	}
	reader := bytes.NewReader(utf8)

	doc, err := goquery.NewDocumentFromReader(reader)
	if err != nil {
		return nil, errors.Wrap(err, "文档解析失败")
	}
	return doc, nil
}

func Convert2Utf8(byte []byte, charset Charset) (b []byte, e error) {
	switch charset {
	case GB18030:
		b, e = simplifiedchinese.GB18030.NewDecoder().Bytes(byte)
	case UTF8:
		fallthrough
	default:
		b = byte
	}

	return
}
